import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from tkinter.font import Font
from analyzer import GitChangeHandler  # 导入 Git 提交分析类
import os
from git import Repo, GitCommandError
import time
import math
import threading
import logging
from logging.handlers import RotatingFileHandler
from configuration import Config
from gui.ToolTip import ToolTip

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from tkinter.font import Font
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.style import Style 
class GitChangeAnalyzerApp:
    """
    Git 变更分析器的 GUI 应用程序。
    """

    def __init__(self, root, config:Config):
        self.root = root
        self.root.title("Git 变更分析器")
        self.root.geometry("900x600")  # 增加窗口大小
        self.root.configure(bg="#f0f0f0")
        self.loading_animation_id = None

        # 加载配置文件
        self.config = config

        # 初始化日志
        self.init_logging()
        # 使用 ttkbootstrap 样式
        self.style = Style(theme=config.theme or "cosmo")
        # 创建菜单栏和GUI组件
        self.create_menu()
        self.create_widgets()
        
        # 检查配置是否完整
        if not self.check_config():
            self.show_centered_message("配置缺失", "请先配置 API Key、Base URL 和 Model！", show_settings=True)

    def save_settings(self):
        """
        保存设置到配置文件。
        """
        self.logger.info("保存配置")
        update_dict = {
            "api_key": str(self.key_entry.get()),
            "base_url": str(self.base_url_entry.get()),
            "max_length": str(self.max_length_entry.get()),
            "model": str(self.model_entry.get()),
            "committer": str(self.committer_entry.get()),
            "current_version": str(self.current_version_entry.get()),
            "commit_format": str(self.commit_format_entry.get()),
            "commit_standard": self.commit_standard_text.get("1.0", tk.END).strip(),
            "enhanced_mode": self.enhanced_mode_var.get()
        }
        self.config.update(update_dict)
        self.settings_window.destroy()  # 关闭设置窗口
        
        # 检查配置是否已经完整
        if self.check_config():
            self.show_centered_message("成功", "配置已保存！")
        else:
            self.show_centered_message("配置缺失", "配置仍然不完整，请检查必填项！", show_settings=True)

    def check_config(self):
        """
        检查配置是否完整有效
        """
        if not self.config.api_key or self.config.api_key == "sk-xxxxxxxxxxxxxxxx":
            self.logger.warning("API Key 未配置")
            return False
        
        if not self.config.base_url:
            self.logger.warning("Base URL 未配置")
            return False
                
        if not self.config.model:
            self.logger.warning("Model 未配置")
            return False
                
        self.logger.info("配置检查通过")
        return True

    def init_logging(self):
        """
        初始化日志记录功能。
        """
        # 日志文件路径设置为执行路径下的 autocommit.log
        log_file = "autocommit.log"

        # 配置日志格式
        log_format = (
            "%(asctime)s [%(levelname)s] "
            "%(filename)s:%(lineno)d - %(funcName)s: "
            "%(message)s"
        )
        date_format = "%Y-%m-%d %H:%M:%S"

        # 配置日志
        logging.basicConfig(
            level=logging.INFO,
            format=log_format,
            datefmt=date_format,
            handlers=[
                RotatingFileHandler(
                    log_file, 
                    maxBytes=5 * 1024 * 1024,  # 每个日志文件最大 5MB
                    backupCount=3,  # 保留 3 个备份
                    encoding='utf-8'
                ),
                logging.StreamHandler()  # 同时输出到控制台
            ]
        )
        self.logger = logging.getLogger(__name__)
        self.logger.info("="*50)
        self.logger.info("应用程序启动")
        self.logger.info(f"当前配置: API Key={'*'*len(self.config.api_key)}, "
                        f"Model={self.config.model}, "
                        f"Base URL={self.config.base_url}")

    def show_processing_dialog(self, message):
        """
        显示处理中的弹窗提示，并居中显示。

        :param message: 提示信息。
        :return: Toplevel 窗口对象。
        """
        self.logger.info(f"显示处理中弹窗: {message}")
        dialog = tk.Toplevel(self.root)
        dialog.title("处理中")
        dialog.configure(bg="#f0f0f0")

        # 计算主窗口的中心位置
        root_x = self.root.winfo_x()
        root_y = self.root.winfo_y()
        root_width = self.root.winfo_width()
        root_height = self.root.winfo_height()
        dialog_width = 300
        dialog_height = 150
        x = root_x + (root_width - dialog_width) // 2
        y = root_y + (root_height - dialog_height) // 2

        # 设置弹窗位置
        dialog.geometry(f"{dialog_width}x{dialog_height}+{x}+{y}")

        # 显示提示信息
        tk.Label(dialog, text=message, font=("Helvetica", 12), bg="#f0f0f0").pack(padx=20, pady=10)

        # 添加动态加载动画
        self.loading_canvas = tk.Canvas(dialog, width=50, height=50, bg="#f0f0f0", highlightthickness=0)
        self.loading_canvas.pack(pady=10)

        # 启动加载动画
        self.start_loading_animation(dialog)

        # 添加状态信息标签
        self.progress_label = tk.Label(dialog, text="", font=("Helvetica", 10), bg="#f0f0f0")
        self.progress_label.pack(pady=5)

        # 禁用主窗口操作
        dialog.grab_set()
        self.root.update()  # 更新界面
        return dialog

    def start_loading_animation(self, dialog):
        """
        启动加载动画（旋转圆圈）。

        :param dialog: 弹窗对象，用于确保动画在弹窗关闭时停止。
        """
        self.loading_angle = 0
        self.loading_radius = 20
        self.loading_center = (25, 25)  # Canvas 的中心点
        self.loading_color = "#0078D7"
        self.loading_speed = 10  # 控制动画速度

        def draw_loading_animation():
            # 清除上一帧
            self.loading_canvas.delete("all")

            # 计算圆点的位置
            x = self.loading_center[0] + self.loading_radius * math.cos(math.radians(self.loading_angle))
            y = self.loading_center[1] + self.loading_radius * math.sin(math.radians(self.loading_angle))

            # 绘制圆点
            self.loading_canvas.create_oval(
                x - 5, y - 5, x + 5, y + 5, fill=self.loading_color, outline=""
            )

            # 更新角度
            self.loading_angle = (self.loading_angle + self.loading_speed) % 360

            # 检查弹窗是否仍然存在
            if dialog.winfo_exists():
                # 继续下一帧
                self.loading_animation_id = self.loading_canvas.after(50, draw_loading_animation)
            else:
                # 弹窗已关闭，停止动画
                self.loading_canvas.delete("all")

        # 启动动画
        draw_loading_animation()


    def stop_loading_animation(self):
        """
        停止加载动画。
        """
        if self.loading_animation_id:
            self.loading_canvas.after_cancel(self.loading_animation_id)
            self.loading_canvas.delete("all")

    def update_progress(self, message):
        """
        更新当前操作的状态信息。

        :param message: 当前操作的状态信息。
        """
        if hasattr(self, 'progress_label'):
            self.progress_label.config(text=message)
            self.progress_label.update()
        else:
            self.logger.info(f"当前状态: {message}")  # 如果没有标签，记录到日志

    def create_widgets(self):
        """
        创建 GUI 组件，并实现动态排版。
        """
        # 设置字体样式
        label_font = Font(family="Helvetica", size=12)
        button_font = Font(family="Helvetica", size=12, weight="bold")

        # 创建主框架
        main_frame = ttk.Frame(self.root, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 仓库选择区域
        repo_frame = ttk.LabelFrame(main_frame, text="仓库选择", padding=10)
        repo_frame.pack(fill=tk.X, pady=(0, 20))

        self.label = ttk.Label(repo_frame, text="本地仓库路径:", font=label_font)
        self.label.pack(side=tk.LEFT, padx=5)

        self.entry = ttk.Entry(repo_frame, width=50, font=label_font)
        self.entry.pack(side=tk.LEFT, expand=True, fill=tk.X, padx=5)
        # 加载上次的路径
        if self.config.last_repo_path:
            self.entry.insert(0, self.config.last_repo_path)
        self.browse_button = ttk.Button(
            repo_frame, 
            text="浏览", 
            command=self.browse_directory,
            style="info.Outline.TButton"
        )
        self.browse_button.pack(side=tk.LEFT, padx=5)

        

        # 提交信息区域
        commit_frame = ttk.LabelFrame(main_frame, text="提交信息", padding=10)
        commit_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 20))

        self.result_text = tk.Text(
            commit_frame, 
            height=10, 
            width=50, 
            font=label_font,
            relief="flat",
            borderwidth=1
        )
        self.result_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        self.result_text.bind("<KeyRelease>", self.adjust_text_height)

        # 按钮区域
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=10)

        # 创建两行按钮
        top_buttons = ttk.Frame(button_frame)
        top_buttons.pack(fill=tk.X, pady=(0, 10))
        
        bottom_buttons = ttk.Frame(button_frame)
        bottom_buttons.pack(fill=tk.X)

        # 第一行按钮
        self.analyze_button = ttk.Button(
            top_buttons, 
            text="分析变更", 
            command=self.analyze_changes,
            style="success.TButton",
            width=20
        )
        self.analyze_button.pack(side=tk.LEFT, expand=True, padx=5)

        self.commit_button = ttk.Button(
            top_buttons, 
            text="提交变更", 
            command=self.commit_changes,
            style="primary.TButton",
            width=20
        )
        self.commit_button.pack(side=tk.LEFT, expand=True, padx=5)

        # 第二行按钮
        self.log_button = ttk.Button(
            bottom_buttons, 
            text="查看提交日志", 
            command=self.view_commit_log,
            style="info.TButton",
            width=20
        )
        self.log_button.pack(side=tk.LEFT, expand=True, padx=5)

        self.rollback_button = ttk.Button(
            bottom_buttons, 
            text="回滚到上一个提交", 
            command=self.rollback_last_commit,
            style="warning.TButton",
            width=20
        )
        self.rollback_button.pack(side=tk.LEFT, expand=True, padx=5)

    def adjust_text_height(self, event=None):
        """
        动态调整提交信息输入框的高度。
        """
        # 获取当前文本内容
        text_content = self.result_text.get("1.0", tk.END)
        # 计算文本行数
        line_count = text_content.count("\n") + 1

        # 设置最大行数（最小5行，最大35行）
        max_lines = max(5, min(line_count, 35))

        # 调整输入框高度
        self.result_text.config(height=max_lines)

    # def create_menu(self):
    #     """
    #     创建菜单栏。
    #     """
    #     menubar = tk.Menu(self.root)
    #     self.root.config(menu=menubar)

    #     # 添加“设置”菜单
    #     settings_menu = tk.Menu(menubar, tearoff=0)
    #     settings_menu.add_command(label="配置设置", command=self.open_settings)
    #     menubar.add_cascade(label="设置", menu=settings_menu)

    def open_settings(self):
        """
        打开设置窗口。
        """
        self.logger.info("打开设置窗口")
        self.settings_window = tk.Toplevel(self.root)
        self.settings_window.title("配置设置")
        self.settings_window.configure(bg="#f0f0f0")
        
        # 设置窗口大小和位置
        settings_width = 600
        settings_height = 700
        self.settings_window.geometry(f"{settings_width}x{settings_height}")
        self.center_window(self.settings_window)
    
        # 设置字体样式
        label_font = Font(family="Helvetica", size=12)
        entry_font = Font(family="Helvetica", size=12)
    
        # 创建主框架，添加内边距
        # main_frame = tk.Frame(self.settings_window, bg="#f0f0f0", padx=20, pady=20)
        # main_frame.pack(fill=tk.BOTH, expand=True)
    
        # 创建主框架和画布
        container = tk.Frame(self.settings_window)
        container.pack(fill=tk.BOTH, expand=True)
        
        # 创建画布和滚动条
        canvas = tk.Canvas(container, bg="#f0f0f0")
        scrollbar = ttk.Scrollbar(container, orient="vertical", command=canvas.yview)
        
        # 创建可滚动的框架
        main_frame = tk.Frame(canvas, bg="#f0f0f0", padx=20, pady=10)  # 减小内边距
        
        # 配置画布滚动区域
        canvas.configure(yscrollcommand=scrollbar.set)
        
        # 打包滚动条和画布
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 在画布上创建窗口
        canvas.create_window((0, 0), window=main_frame, anchor="nw")
        
        # 创建固定在底部的按钮框架
        button_frame = tk.Frame(self.settings_window, bg="#f0f0f0", pady=5)
        button_frame.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 保存按钮
        save_button = ttk.Button(button_frame, text="保存", command=self.save_settings, style="Accent.TButton")
        save_button.pack(pady=5)

        # 配置画布的滚动区域
        def configure_scroll_region(event):
            # 获取主框架的实际高度
            main_frame_height = main_frame.winfo_reqheight()
            # 获取画布的可见高度
            canvas_height = canvas.winfo_height()
            # 设置滚动区域
            if main_frame_height > canvas_height:
                canvas.configure(scrollregion=(0, 0, 0, main_frame_height))
            else:
                canvas.configure(scrollregion=(0, 0, 0, canvas_height))
        
        # 绑定配置事件
        main_frame.bind("<Configure>", configure_scroll_region)
        canvas.bind("<Configure>", lambda e: configure_scroll_region(None))
        
        # 绑定鼠标滚轮事件
        def on_mousewheel(event):
            if canvas.yview() != (0.0, 1.0):  # 只有当内容超出显示范围时才允许滚动
                canvas.yview_scroll(int(-1*(event.delta/120)), "units")
        
        canvas.bind_all("<MouseWheel>", on_mousewheel)
        # 保存按钮放在固定的底部框架中
        # save_button = ttk.Button(button_frame, text="保存", command=self.save_settings, style="Accent.TButton")
        # save_button.pack(pady=5)

        # API设置区域
        api_frame = tk.LabelFrame(main_frame, text="API 设置", font=label_font, bg="#f0f0f0", padx=10, pady=10)
        api_frame.pack(fill=tk.X, pady=(0, 20))

        # API Key 设置
        tk.Label(api_frame, text="API Key:", font=label_font, bg="#f0f0f0").grid(row=0, column=0, padx=10, pady=5, sticky="e")
        self.key_entry = tk.Entry(api_frame, width=40, font=entry_font)
        self.key_entry.grid(row=0, column=1, padx=10, pady=5)
        self.key_entry.insert(0, self.config.api_key)

        # 模型厂商选择
        tk.Label(api_frame, text="模型厂商:", font=label_font, bg="#f0f0f0").grid(row=1, column=0, padx=10, pady=5, sticky="e")
        self.vendor_var = tk.StringVar(value='阿里通义')  # 设置初始值
        self.vendor_combobox = ttk.Combobox(api_frame, textvariable=self.vendor_var, values=list(self.config.vendor_urls.keys()), 
                                           width=38, font=entry_font, state="readonly")
        self.vendor_combobox.grid(row=1, column=1, padx=10, pady=5, sticky="w")
        self.vendor_combobox.bind("<<ComboboxSelected>>", self.on_vendor_change)

        # Base URL 输入框
        tk.Label(api_frame, text="Base URL:", font=label_font, bg="#f0f0f0").grid(row=2, column=0, padx=10, pady=5, sticky="e")
        self.base_url_entry = tk.Entry(api_frame, width=40, font=entry_font)
        self.base_url_entry.grid(row=2, column=1, padx=10, pady=5)
        self.base_url_entry.insert(0, self.config.base_url)
    
        # Max Length 输入框
        tk.Label(api_frame, text="可输入最大长度:", font=label_font, bg="#f0f0f0").grid(row=3, column=0, padx=10, pady=5, sticky="e")
        self.max_length_entry = tk.Entry(api_frame, width=40, font=entry_font)
        self.max_length_entry.grid(row=3, column=1, padx=10, pady=5)
        self.max_length_entry.insert(0, self.config.max_length)
    
        # Model 输入框
        tk.Label(api_frame, text="可用模型名称:", font=label_font, bg="#f0f0f0").grid(row=4, column=0, padx=10, pady=5, sticky="e")
        self.model_entry = tk.Entry(api_frame, width=40, font=entry_font)
        self.model_entry.grid(row=4, column=1, padx=10, pady=5)
        self.model_entry.insert(0, self.config.model)
    
        # Git提交设置区域
        git_frame = tk.LabelFrame(main_frame, text="Git 提交设置", font=label_font, bg="#f0f0f0", padx=10, pady=10)
        git_frame.pack(fill=tk.X, pady=(0, 20))
    
        tk.Label(git_frame, text="提交人名字:", font=label_font, bg="#f0f0f0").grid(row=0, column=0, padx=10, pady=5, sticky="e")
        self.committer_entry = tk.Entry(git_frame, width=40, font=entry_font)
        self.committer_entry.grid(row=0, column=1, padx=10, pady=5)
        self.committer_entry.insert(0, self.config.committer)
    
        tk.Label(git_frame, text="当前版本:", font=label_font, bg="#f0f0f0").grid(row=1, column=0, padx=10, pady=5, sticky="e")
        self.current_version_entry = tk.Entry(git_frame, width=40, font=entry_font)
        self.current_version_entry.grid(row=1, column=1, padx=10, pady=5)
        self.current_version_entry.insert(0, self.config.current_version)
    
        tk.Label(git_frame, text="提交格式:", font=label_font, bg="#f0f0f0").grid(row=2, column=0, padx=10, pady=5, sticky="e")
        self.commit_format_entry = tk.Entry(git_frame, width=40, font=entry_font)
        self.commit_format_entry.grid(row=2, column=1, padx=10, pady=5)
        self.commit_format_entry.insert(0, self.config.commit_format)
    
        # 提交信息设置区域
        commit_frame = tk.LabelFrame(main_frame, text="提交信息设置", font=label_font, bg="#f0f0f0", padx=10, pady=10)
        commit_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 20))
    
        tk.Label(commit_frame, text="提交信息类型:", font=label_font, bg="#f0f0f0").pack(anchor="w", padx=10, pady=5)
        self.commit_standard_text = tk.Text(commit_frame, height=8, width=50, font=entry_font)
        self.commit_standard_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        self.commit_standard_text.insert(tk.END, self.config.commit_standard)
    
        # 增强模式设置
        self.enhanced_mode_var = tk.BooleanVar(value=self.config.enhanced_mode)
        self.enhanced_mode_checkbutton = tk.Checkbutton(
            main_frame,
            text="启用增强模式",
            font=label_font,
            bg="#f0f0f0",
            variable=self.enhanced_mode_var
        )
        self.enhanced_mode_checkbutton.pack(pady=10)
    
        # 添加 ToolTip
        ToolTip(
            self.enhanced_mode_checkbutton,
            text="启用增强模式会分析整个项目结构以及每个文件，综合生成提交信息，更加智能，相应时间会更久。"
        )
    
        # 删除这个多余的保存按钮
        # ttk.Button(main_frame, text="保存", command=self.save_settings, style="Accent.TButton").pack(pady=20)

    def center_window(self, window):
        # 居中窗口
        window.update_idletasks()
        width = window.winfo_width()
        height = window.winfo_height()
        x = (window.winfo_screenwidth() // 2) - (width // 2)
        y = (window.winfo_screenheight() // 2) - (height // 2)
        window.geometry(f'{width}x{height}+{x}+{y}')

    def create_menu(self):
        """
        创建菜单栏。
        """
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)

        # 添加"设置"菜单
        settings_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="设置", menu=settings_menu)
        
        # 添加配置设置选项
        settings_menu.add_command(label="配置设置", command=self.open_settings)
        
        # 添加主题子菜单
        theme_menu = tk.Menu(settings_menu, tearoff=0)
        settings_menu.add_cascade(label="主题设置", menu=theme_menu)
        
        # 添加主题选项
        themes = ['cosmo', 'flatly', 'litera', 'minty', 'lumen', 
                    'sandstone', 'yeti', 'pulse', 'united', 'morph', 
                    'darkly', 'superhero', 'solar', 'cyborg']
        
        self.theme_var = tk.StringVar(value=self.style.theme.name)
        for theme in themes:
            theme_menu.add_radiobutton(
                label=theme,
                value=theme,
                variable=self.theme_var,
                command=lambda t=theme: self.change_theme(t)
            )

    def change_theme(self, theme_name):
        """
        切换应用主题
        """
        self.style.theme_use(theme_name)
        self.config.theme = theme_name
        self.config.update({"theme": theme_name})



    def save_settings(self):
        """
        保存设置到配置文件。
        """
        self.logger.info("保存配置")
        update_dict = {
            "api_key": str(self.key_entry.get()),
            "base_url": str(self.base_url_entry.get()),
            "max_length": str(self.max_length_entry.get()),
            "model": str(self.model_entry.get()),
            "committer": str(self.committer_entry.get()),  # 获取提交人名字
            "current_version": str(self.current_version_entry.get()),
            "commit_format": str(self.commit_format_entry.get()),
            "commit_standard": self.commit_standard_text.get("1.0", tk.END).strip(),
            "enhanced_mode": self.enhanced_mode_var.get()
        }
        self.config.update(update_dict)

        self.settings_window.destroy()  # 关闭设置窗口

    def on_vendor_change(self, event=None):
        """
        当选择不同的模型厂商时更新 base_url
        """
        selected_vendor = self.vendor_var.get()
        self.base_url_entry.config(state="normal")  # 先解除只读状态
        self.base_url_entry.delete(0, tk.END)
        
        if selected_vendor == "自定义":
            # 保持输入框为可编辑状态
            self.base_url_entry.insert(0, "")
        else:
            # 插入预设值后设为只读
            self.base_url_entry.insert(0, self.config.vendor_urls.get(selected_vendor, ""))
            self.base_url_entry.config(state="readonly")
            self.base_url_entry.config(state="normal")
            # self.base_url_entry.delete(0, tk.END)
            # self.base_url_entry.insert(0, self.config.vendor_urls.get(selected_vendor, ""))
            # self.base_url_entry.config(state="readonly")

    
    def browse_directory(self):
        """
        打开目录选择对话框，选择 Git 仓库路径。
        """
        directory = filedialog.askdirectory()
        if directory:
            self.entry.delete(0, tk.END)
            self.entry.insert(0, directory)
            # 保存选择的路径
            self.config.update({"last_repo_path": directory})
            self.logger.info(f"选择 Git 仓库路径: {directory}")

    def show_centered_message(self, title, message, show_settings=False):
        """
        在应用程序中央显示信息弹窗。
        """
        self.logger.info(f"显示弹窗: {title} - {message}")
        dialog = tk.Toplevel(self.root)
        dialog.title(title)
        dialog.configure(bg="#f0f0f0")
        dialog.transient(self.root)
    
        # 设置最小尺寸
        dialog_width = 400  # 增加宽度
        dialog_height = 200  # 增加高度
    
        # 添加消息内容
        tk.Label(dialog, text=message, font=("Helvetica", 12), wraplength=350, bg="#f0f0f0").pack(padx=30, pady=30)
    
        # 创建按钮框架
        button_frame = tk.Frame(dialog, bg="#f0f0f0")
        button_frame.pack(pady=20)
    
        if show_settings:
            def confirm_and_settings():
                dialog.destroy()
                self.open_settings()
            ttk.Button(button_frame, text="确定", command=confirm_and_settings, style="Accent.TButton").pack(side=tk.LEFT, padx=5)
        else:
            ttk.Button(button_frame, text="确定", command=dialog.destroy, style="Accent.TButton").pack(side=tk.LEFT, padx=5)
        
        # 禁用主窗口操作
        dialog.grab_set()
        
        # 等待窗口绘制完成
        dialog.update_idletasks()
        
        # 判断主窗口是否已经显示
        if self.root.winfo_width() > 1:  # 主窗口已显示
            root_x = self.root.winfo_x()
            root_y = self.root.winfo_y()
            root_width = self.root.winfo_width()
            root_height = self.root.winfo_height()
            x = root_x + (root_width - dialog_width) // 2
            y = root_y + (root_height - dialog_height) // 2
        else:  # 主窗口未显示，相对于屏幕居中
            screen_width = dialog.winfo_screenwidth()
            screen_height = dialog.winfo_screenheight()
            x = (screen_width - dialog_width) // 2
            y = (screen_height - dialog_height) // 2
        
        # 设置弹窗位置
        dialog.geometry(f"{dialog_width}x{dialog_height}+{x}+{y}")

        # # 添加消息内容
        # tk.Label(dialog, text=message, font=("Helvetica", 12), wraplength=250, bg="#f0f0f0").pack(padx=20, pady=20)

        # 添加关闭按钮
        ttk.Button(dialog, text="关闭", command=dialog.destroy, style="Accent.TButton").pack(pady=10)

        # 禁用主窗口操作
        dialog.grab_set()

    def analyze_changes(self):
        """
        功能：
        1.根据 Git 变更并生成提交信息。
        2.根据项目文件内容，以及git变更信息生成提交（增强模式）
        """
        repo_path = self.entry.get()
        if not self.check_settings(repo_path=repo_path):
            self.logger.info("检查配置文件失败，请检查配置")
            return
        summary=''

        # 显示处理中的弹窗
        processing_dialog = self.show_processing_dialog("正在分析变更\n提交变更文件较大的情况下\n可能会稍慢，请耐心等候...")

        try:

            # 调用 GitChangeHandler 生成提交信息
            commit_message = GitChangeHandler(repo_path=repo_path, config=self.config).generate_commit_message()

            # 检查是否生成提交信息失败
            if "生成提交信息失败" in commit_message or commit_message == "没有检测到 Git 变更。" or "调用GPT失败" in commit_message:
                self.show_centered_message("错误", commit_message)
            else:
                # 只有在生成成功时才更新输入框内容
                self.result_text.delete(1.0, tk.END)  # 清空文本框
                self.result_text.insert(tk.END, commit_message)
                self.logger.info(f"生成提交信息: {commit_message}")
        except Exception as e:
            self.logger.error(f"分析变更时出错: {e}")
            self.show_centered_message("错误", f"分析变更时出错: {e}")
        finally:
            processing_dialog.destroy()  # 关闭处理中的弹窗

    # def commit_changes(self):
    #     """
    #     提交变更到远程仓库。
    #     """
    #     repo_path = self.entry.get()
    #     if not repo_path:
    #         self.show_centered_message("错误", "请选择 Git 仓库路径！")
    #         return
    #
    #     commit_message = self.result_text.get(1.0, tk.END).strip()
    #     if not commit_message:
    #         self.show_centered_message("错误", "请填写提交信息！")
    #         return
    #
    #     # 显示处理中的弹窗
    #     processing_dialog = self.show_processing_dialog("正在提交变更，请稍候...")
    def check_settings(self,repo_path):
        """
        功能：
            1. 检查并返回 Git 仓库是否存在。
            2. 检查并返回是否有未提交的变更。
            3. 检查配置是否存在
        """

        if not repo_path:
            self.show_centered_message("错误", "请选择 Git 仓库路径！")
            return False

        if not os.path.exists(os.path.join(repo_path, ".git")):
            self.show_centered_message("错误", "选择的目录不是 Git 仓库！")
            return False
        if self.config.api_key is None or not self.config.api_key or self.config.base_url is  None or self.config.model is  None:
            self.show_centered_message("配置缺失", "请在设置中先配置 API Key、Base URL 和 Model！")
            return False
        return True



    def commit_changes(self):
        """
        提交变更到远程仓库，禁止空的提交。
        """
        repo_path = self.entry.get()
        if not repo_path:
            self.show_centered_message("错误", "请选择 Git 仓库路径！")
            return

        commit_message = self.result_text.get(1.0, tk.END).strip()
        if not commit_message:
            self.show_centered_message("错误", "请填写提交信息！")
            return

        # 显示处理中的弹窗
        processing_dialog = self.show_processing_dialog("正在提交变更，请稍候...")

        # 使用多线程执行提交操作
        def submit_in_thread():
            try:
                repo = Repo(repo_path)

                # 检查是否有未暂存的变更
                self.update_progress("正在检查变更...")
                changes = repo.index.diff(None)  # 获取未暂存的变更
                staged_changes = repo.index.diff("HEAD")  # 获取已暂存的变更

                if not changes and not staged_changes:
                    self.show_centered_message("提示", "没有检测到变更，无需提交！")
                    return

                # 阶段 1: 添加文件
                self.update_progress("正在添加文件...")
                repo.git.add(A=True)
                time.sleep(1)  # 模拟延迟

                # 阶段 2: 提交变更
                self.update_progress("正在提交变更...")
                repo.index.commit(commit_message)
                time.sleep(1)  # 模拟延迟

                # 获取当前分支名称
                current_branch = repo.active_branch.name

                # 检查远程分支是否存在
                remote_branch_exists = False
                for ref in repo.remotes.origin.refs:
                    if ref.name == f"origin/{current_branch}":
                        remote_branch_exists = True
                        break

                if not remote_branch_exists:
                    # 阶段 3: 创建并推送新分支
                    self.update_progress("正在创建并推送新分支...")
                    repo.git.push("--set-upstream", "origin", current_branch)
                    self.show_centered_message("成功",
                                               f"远程分支 {current_branch} 不存在，已创建并推送新分支！\n推送的分支名称: {current_branch}")
                else:
                    # 阶段 3: 推送到远程仓库
                    self.update_progress("正在推送到远程仓库...")
                    repo.remotes.origin.push()
                    self.show_centered_message("成功", "变更已提交并推送到远程仓库！")

                # 完成
                self.update_progress("提交完成！")
                self.logger.info("提交变更成功")

            except GitCommandError as e:
                self.logger.error(f"提交或推送失败: {e}")
                self.show_centered_message("错误", f"提交或推送失败: {e}")
            finally:
                # 停止加载动画
                self.stop_loading_animation()
                # 延迟关闭弹窗，确保用户看到完成状态
                self.root.after(1000, processing_dialog.destroy)  # 1秒后关闭弹窗

        # 启动线程
        threading.Thread(target=submit_in_thread).start()

    def view_commit_log(self):
        """
        查看 Git 提交日志。
        """
        repo_path = self.entry.get()
        if not repo_path:
            self.show_centered_message("错误", "请选择 Git 仓库路径！")
            return

        # 显示处理中的弹窗
        processing_dialog = self.show_processing_dialog("正在获取提交日志，请稍候...")

        try:
            repo = Repo(repo_path)
            log = repo.git.log(oneline=True)
            self.show_centered_message("提交日志", log)
            self.logger.info("查看提交日志")
        except GitCommandError as e:
            self.logger.error(f"获取提交日志失败: {e}")
            self.show_centered_message("错误", f"获取提交日志失败: {e}")
        finally:
            processing_dialog.destroy()  # 关闭处理中的弹窗

    def rollback_last_commit(self):
        """
        回滚到上一个提交。
        """
        repo_path = self.entry.get()
        if not repo_path:
            self.show_centered_message("错误", "请选择 Git 仓库路径！")
            return

        # 创建确认弹窗
        confirm_dialog = tk.Toplevel(self.root)
        confirm_dialog.title("确认回滚")
        confirm_dialog.configure(bg="#f0f0f0")
        confirm_dialog.transient(self.root)
        
        # 设置弹窗大小
        dialog_width = 300
        dialog_height = 150
        
        # 添加警告信息
        tk.Label(
            confirm_dialog, 
            text="警告：回滚操作将丢失最近一次的提交记录！\n确定要继续吗？", 
            font=("Helvetica", 12), 
            wraplength=250, 
            bg="#f0f0f0"
        ).pack(padx=20, pady=20)
        
        # 按钮框架
        button_frame = tk.Frame(confirm_dialog, bg="#f0f0f0")
        button_frame.pack(pady=10)
        
        def confirm_rollback():
            confirm_dialog.destroy()
            # 显示处理中的弹窗
            processing_dialog = self.show_processing_dialog("正在回滚到上一个提交，请稍候...")
            
            try:
                repo = Repo(repo_path)
                repo.git.reset("--hard", "HEAD~1")
                self.show_centered_message("成功", "已回滚到上一个提交！")
                self.logger.info("回滚到上一个提交成功")
            except GitCommandError as e:
                self.logger.error(f"回滚失败: {e}")
                self.show_centered_message("错误", f"回滚失败: {e}")
            finally:
                processing_dialog.destroy()
        
        # 确认和取消按钮
        ttk.Button(button_frame, text="确定", command=confirm_rollback, style="Accent.TButton").pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="取消", command=confirm_dialog.destroy, style="Accent.TButton").pack(side=tk.LEFT, padx=5)
        
        # 居中显示弹窗
        self.center_window(confirm_dialog)
        
        # 禁用主窗口操作
        confirm_dialog.grab_set()


# 主程序
if __name__ == "__main__":
    root = tk.Tk()

    app = GitChangeAnalyzerApp(root,config=Config())
    root.mainloop()